#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/time.h>
#include <netinet/in.h>

#include "socket.c"
#include "utils.c"
#include "protocol.h"

#define SERVER_ADDR "127.0.0.1"
#define SERVER_PORT 8000

#define PROTO_VER 1

enum state{
	OFFLINE = 0,
	//CONNECT = 1
};
uint8_t client_state = OFFLINE;
long long int timeout = 0;
uint8_t client_id[] = "Test123";

int packet_send(int fd, uint8_t *sbuf, size_t slen){
	if(slen > 1400) return -1;
	
	uint8_t rbuf[1500];
	size_t rlen = sizeof(rbuf);
	
	int ret = 0;
	long long int t = iclock();
	while(1){
		ret = recv(fd, rbuf, rlen, 0);
		if(ret >=0){
			//has data
			printf("%lld\n", iclock()-t);
			break;
		}else if(errno == EAGAIN){
			//timeout and send agains
			send(fd, sbuf, slen, 0);
			t = iclock();
		}
	}
	
	return ret;
}

/*uint8_t *buf, size_t size*/
int send_connect(int fd){
	typedef struct {
		uint8_t type:8;
		uint8_t ver:8;
		//ecdh
		EccPoint pub_key;
		uint8_t random[NUM_ECC_DIGITS];
		//start enc data
		uint8_t data;
	}head;

	char buf[1400];
	head *h = (head *)buf;

	//fill head
	h->type = CONNECT;
	h->ver = PROTO_VER;

	//gen private key
	ecc_gen_key(&h->pub_key, cli_pri_key);
	//gen random number
	gen_random_bytes(h->random, NUM_ECC_DIGITS);
	//gen share serret
	ecdh_shared_secret(share_secret, &ser_pub_key, cli_pri_key, h->random);
	//set aes secret
	aes_set_secret(share_secret, h->random);

	memcpy(&h->data, client_id, sizeof(client_id));

	//encrypt data
	aes_ctr_cipher(&h->data, sizeof(client_id));

	//hex_print(share_secret, NUM_ECC_DIGITS);

	struct {
		uint8_t qos:1;//qos level
		uint8_t type:5;//messages type
		uint8_t len:2;//the length len
	}p_head;

	p_head.qos = 1;
	p_head.type = 1;
	p_head.len = 1;

	buf[0] = *((uint8_t *)&p_head);

	packet_send(fd, buf, sizeof(head)+sizeof(client_id) -1);
	//printf("%d\n", ret);

	return 0;
}


int packet_recv(int fd){
	char buf[1000];

	int ret = recv(fd, buf, sizeof(buf), 0);
	if(ret >= 0){
		//has data
		printf("%d \n", ret ,buf);
	}else if(errno == EAGAIN){
		//timeout
		switch(client_state){
			case OFFLINE:
				send_connect(fd);
				break;
			default:
				break;
		}
		//printf("%lld\n", iclock());
		
	}
	return ret;
}

void serivce_start(char *addr, int port){
	int sockfd = socket_init(addr, port);
	
	while(1){
		packet_recv(sockfd);
	}
}

int main(){
	
	serivce_start(SERVER_ADDR, SERVER_PORT);	
	return 0;
}

